<!DOCTYPE html>
<html>
<head>
    <title>数据比较工具</title>
    <script src="/assets/js/jquery-3.7.1.min.js"></script>
    <style>
        /* 全局样式 */
        body {
            font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
            background-color: #f5f9f6;
            color: #333;
            margin: 0;
            padding: 20px;
            line-height: 1.6;
        }

        h2 {
            color: #2e7d32;
            text-align: center;
            margin-bottom: 30px;
            font-weight: 600;
            text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
            border-bottom: 2px solid #a5d6a7;
            padding-bottom: 10px;
        }

        h3 {
            color: #388e3c;
            margin-top: 0;
            font-weight: 500;
        }

        /* 输入区域样式 */
        .config-input {
            margin-bottom: 20px;
            background-color: white;
            padding: 15px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.05);
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
        }

        .config-input:hover {
            box-shadow: 0 4px 15px rgba(0,0,0,0.1);
        }

        .config-input label {
            display: inline-block;
            width: 100px;
            color: #2e7d32;
            font-weight: 500;
            margin-right: 10px;
        }

        input {
            flex: 1;
            width: 100%;
            height: 36px;
            border: 1px solid #c8e6c9;
            border-radius: 4px;
            padding: 0 10px;
            font-size: 14px;
            transition: border 0.3s;
            outline: none;
        }

        input:focus {
            border-color: #4caf50;
            box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.2);
        }

        /* 表格样式 */
        table {
            width: 100%;
            border-collapse: collapse;
            margin-bottom: 20px;
        }

        td {
            padding: 15px;
            vertical-align: top;
        }

        /* 文本区域样式 */
        textarea {
            width: 100%;
            border: 1px solid #c8e6c9;
            border-radius: 8px;
            padding: 10px;
            font-size: 14px;
            resize: vertical;
            transition: border 0.3s;
            outline: none;
            box-shadow: inset 0 1px 3px rgba(0,0,0,0.05);
        }

        textarea:focus {
            border-color: #4caf50;
            box-shadow: inset 0 1px 3px rgba(0,0,0,0.05), 0 0 0 2px rgba(76, 175, 80, 0.2);
        }

        /* 按钮样式 */
        button, .sort {
            background-color: #4caf50;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
            font-weight: 500;
            transition: all 0.3s;
            box-shadow: 0 2px 5px rgba(0,0,0,0.1);
            margin-right: 10px;
            outline: none;
        }

        button:hover, .sort:hover {
            background-color: #388e3c;
            box-shadow: 0 4px 8px rgba(0,0,0,0.15);
            transform: translateY(-1px);
        }

        button:active, .sort:active {
            background-color: #2e7d32;
            transform: translateY(1px);
            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
        }

        /* 数据表格样式 */
        #table-container table, #table-container2 table, #compare-container table {
            width: 100%;
            border-collapse: collapse;
            border-radius: 8px;
            overflow: hidden;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            background-color: white;
        }

        #table-container table td, #table-container2 table td, #compare-container table td,
        #table-container table th, #table-container2 table th, #compare-container table th {
            border: 1px solid #e0e0e0;
            padding: 10px;
            text-align: left;
        }

        #table-container table th, #table-container2 table th, #compare-container table th {
            background-color: #81c784;
            color: white;
            font-weight: 500;
            text-transform: uppercase;
            font-size: 12px;
            letter-spacing: 1px;
        }

        #table-container table tr:nth-child(even), 
        #table-container2 table tr:nth-child(even), 
        #compare-container table tr:nth-child(even) {
            background-color: #f5f9f6;
        }

        #table-container table tr:hover, 
        #table-container2 table tr:hover, 
        #compare-container table tr:hover {
            background-color: #e8f5e9;
        }

        /* 高亮行样式 */
        tr[style*="background-color: #ffcccc"] {
            background-color: #ffebee !important;
            border-left: 4px solid #ef5350;
        }

        /* 合计行样式 */
        tr:last-child td[style*="background-color: #f0f0f0"] {
            background-color: #e8f5e9 !important;
            color: #2e7d32;
            font-weight: 600;
        }

        /* 响应式设计 */
        @media (max-width: 1200px) {
            input {
                width: 100%;
                max-width: 500px;
            }
        }

        /* 工具提示 */
        .tooltip {
            position: relative;
            display: inline-block;
            margin-left: 5px;
            color: #81c784;
            cursor: help;
        }

        .tooltip .tooltiptext {
            visibility: hidden;
            width: 200px;
            background-color: #555;
            color: #fff;
            text-align: center;
            border-radius: 6px;
            padding: 5px;
            position: absolute;
            z-index: 1;
            bottom: 125%;
            left: 50%;
            margin-left: -100px;
            opacity: 0;
            transition: opacity 0.3s;
        }

        .tooltip:hover .tooltiptext {
            visibility: visible;
            opacity: 1;
        }
    </style>
</head>
<body>
<h2>数据比较分析工具</h2>
<div class="config-input">
    <label>查询字段:</label>
    <input type="text" id="idname" value="结算号" placeholder="输入要找到字段，如两表都有的相同记录编号">
    <span class="tooltip">?<span class="tooltiptext">输入两个表格中共有的唯一标识字段</span></span>
</div>
<div class="config-input">
    <label>比较字段:</label>
    <input type="text" id="compareFields" value="借方金额,贷方金额"
           placeholder="输入要比较字段（可多个，用半角的逗号分隔）">
    <span class="tooltip">?<span class="tooltiptext">输入需要比较的字段，多个字段用逗号分隔</span></span>
</div>
<div class="config-input">
    <label>对齐字段:</label>
    <input type="text" id="sortFields" value="借方金额,贷方金额" placeholder="输入要排序字段（可多个，用半角的逗号分隔）">
    <span class="tooltip">?<span class="tooltiptext">输入需要对齐的字段，多个字段用逗号分隔</span></span>
</div>
<p style="text-align: center; color: #388e3c; margin-bottom: 20px;">将从Excel表格复制过来的两组数据，根据指定字段进行智能比较分析</p>
<table style="width: 100%; border-collapse: collapse;">
    <tr>
        <td style="width: 50%; padding: 10px; vertical-align: top;text-align: right;float: right;">
            <h3>第一组数据处理</h3>
        </td>
        <td style="width: 50%; padding: 10px; vertical-align: top;">
            <h3>第二组数据处理</h3>
        </td>
    </tr>
    <tr>
        <td style="padding: 10px;text-align: right;">
            <textarea id="input" rows="10" cols="50" placeholder="在此输入内容..."></textarea><br><br>
            <button onclick="convertTabs('input', 'output', 'json-output', 'table-container')">生成对比表格</button>
        </td>
        <td style="padding: 10px;">
            <textarea id="input2" rows="10" cols="50" placeholder="在此输入第二组内容..."></textarea><br><br>
            <button onclick="convertTabs('input2', 'output2', 'json-output2', 'table-container2')">生成对比表格</button>
            <button onclick="compareJsonData()" id="compareJsonData">比较两组数据</button>
            <input type="button" class="sort" value="对齐比较" style="width:80px"/>
        </td>
    </tr>
    <tr>
        <td style="padding: 10px">
            <textarea id="output" rows="10" cols="50" placeholder="转换结果将显示在这里..." readonly
                      style="display:none"></textarea>
        </td>
        <td style="padding: 10px;">
            <textarea id="output2" rows="10" cols="50" placeholder="第二组转换结果将显示在这里..." readonly
                      style="display:none"></textarea>
        </td>
    </tr>
    <tr>
        <td style="padding: 10px;">
            <textarea id="json-output" rows="10" cols="50" placeholder="JSON输出将显示在这里..." readonly
                      style="display:none"></textarea>
        </td>
        <td style="padding: 10px;">
            <textarea id="json-output2" rows="10" cols="50" placeholder="第二组JSON输出将显示在这里..." readonly
                      style="display:none"></textarea>
        </td>
    </tr>
    <tr>
        <td colspan="2" style="padding: 10px;text-align: right;float: right;">
            <div id="compare-container">
                <!-- 比较结果将显示在这里 -->
            </div>
        </td>
    </tr>
    <tr>
        <td style="padding: 10px;;vertical-align:top">
            <div id="table-container" style="text-align: right;">
                <!-- 第一组表格将显示在这里 -->
            </div>
        </td>
        <td style="padding: 10px;vertical-align:top">
            <div id="table-container2">
                <!-- 第二组表格将显示在这里 -->
            </div>
        </td>
    </tr>

</table>

<script>
    function convertTabs(inputId, outputId, jsonOutputId, tableContainerId) {
        try {
            $('#' + outputId).html("");
            $('#' + tableContainerId).html("");
            // 获取输入内容
            const input = document.getElementById(inputId).value;
            if (!input.trim()) {
                console.warn('输入为空，无法处理');
                return;
            }
            // 将制表符替换为\t
            const output = input.replace(/\t/g, '\\t');
            // 显示转换结果
            document.getElementById(outputId).value = output;

            // 获取表格容器
            const tableContainer = document.getElementById(tableContainerId);

            // 检查是否已经存在表格
            let table = tableContainer.querySelector('table');
            if (!table) {
                // 如果不存在表格，则创建新表格和表头
                table = document.createElement('table');
                table.style.border = '1px solid black';
                table.style.borderCollapse = 'collapse';
                tableContainer.appendChild(table);
            } else {
                // 如果存在表格，则清空数据行（保留表头）
                while (table.rows.length > 1) {
                    table.deleteRow(1);
                }
            }

            // 按行分割
            const rows = output.split('\n');
            const data = [];

            // 首先收集所有数据
            rows.forEach(row => {
                if (row.trim() === '') return;
                const cells = row.split('\\t').map(cell => cell.trim());
                data.push(cells);
            });

            // 找出需要删除的列索引
            const columnsToRemove = new Set();
            if (data.length > 0) {
                for (let col = 0; col < data[0].length; col++) {
                    let isEmpty = true;
                    for (let row = 0; row < data.length; row++) {
                        if (data[row][col] && data[row][col] !== '') {
                            isEmpty = false;
                            break;
                        }
                    }
                    if (isEmpty) {
                        columnsToRemove.add(col);
                    }
                }
            }
            const jsonData = [];
            // 生成表格
            data.forEach((row, rowIndex) => {
                // 过滤空列
                const filteredRow = row.filter((_, index) => !columnsToRemove.has(index));
                // 如果第一列为空或整行都为空则跳过
                if (filteredRow.length === 0 || filteredRow[0] === '') return;

                const tr = document.createElement('tr');
                const rowData = {};
                filteredRow.forEach((cell, index) => {
                    const td = document.createElement('td');
                    td.textContent = cell;
                    td.style.border = '1px solid black';
                    td.style.padding = '5px';
                    td.style.verticalAlign = 'top';
                    td.style.maxHeight = '50px';  // 固定高度
                    td.style.maxWidth = '30vw';   // 最大宽度为页面宽度的30%
                    td.style.overflow = 'hidden'; // 超出部分隐藏
                    td.style.whiteSpace = 'nowrap'; // 禁止换行
                    td.style.textOverflow = 'ellipsis'; // 超出显示省略号
                    tr.appendChild(td);
                    rowData[`column${index + 1}`] = cell;
                });
                table.appendChild(tr);
                jsonData.push(rowData);
            });

            // 将数据转换为JSON并输出
            document.getElementById(jsonOutputId).value = JSON.stringify(jsonData);
        } catch (error) {
            console.error('处理数据时出错:', error);
            alert('处理数据时出错: ' + error.message);
        }
    }

    function compareJsonData() {

        convertTabs('input', 'output', 'json-output', 'table-container');
        convertTabs('input2', 'output2', 'json-output2', 'table-container2')

        // 获取两组JSON数据
        const json1 = JSON.parse(document.getElementById('json-output').value);
        const json2 = JSON.parse(document.getElementById('json-output2').value);

        // 获取表头信息
        const table1 = document.querySelector('#table-container table');
        const table2 = document.querySelector('#table-container2 table');

        // 获取列索引
        const getColumnIndex = (table, columnName) => {
            // 获取第一行数据
            const firstRow = table.querySelector('tr');
            if (!firstRow) return -1;

            // 获取所有单元格
            const cells = firstRow.querySelectorAll('td');
            for (let i = 0; i < cells.length; i++) {
                if (cells[i].textContent.includes(columnName)) {
                    return i;
                }
            }
            return -1;
        };

        // 获取用户输入的配置
        const idname = document.getElementById('idname').value.trim();
        const compareFields = document.getElementById('compareFields').value
            .split(/[,，或 　]/)  // 使用正则表达式匹配中文逗号和"或"
            .map(f => f.trim())
            .filter(f => f.length > 0);  // 过滤空值

        // 获取比较字段的列索引
        const getFieldIndices = (table) => {
            const indices = {[idname]: getColumnIndex(table, idname)};
            compareFields.forEach(field => {
                indices[field] = getColumnIndex(table, field);
            });
            return indices;
        };

        // 获取比较字段的列索引
        const fields1 = getFieldIndices(table1);
        const fields2 = getFieldIndices(table2);

        // 创建比较结果容器
        const compareContainer = document.getElementById('compare-container');
        compareContainer.innerHTML = '';

        // 创建表格
        const table = document.createElement('table');
        table.style.border = '1px solid black';
        table.style.borderCollapse = 'collapse';

        // 创建表头
        const headerRow = document.createElement('tr');
        const headerFields = [idname];
        compareFields.forEach(field => {
            headerFields.push(`第一组${field}`);
            headerFields.push(`第二组${field}`);
        });

        headerFields.forEach(text => {
            const th = document.createElement('th');
            th.textContent = text;
            th.style.border = '1px solid black';
            th.style.padding = '5px';
            headerRow.appendChild(th);
        });
        table.appendChild(headerRow);

        // 创建映射以快速查找，处理重复数据
        // 使用Map存储每个键对应的所有值
        const map1 = new Map();
        json1.forEach(item => {
            const id = fields1[idname] !== -1 ? item[`column${fields1[idname] + 1}`] : null;
            if (!id || id.trim() === '') return;
            
            const values = {};
            compareFields.forEach(field => {
                const index = fields1[field];
                // 格式化金额：去除千位分隔符，保留两位小数
                const value = item[`column${index + 1}`]?.replace(/,/g, '');
                values[field] = index !== -1 && !isNaN(parseFloat(value)) ?
                    parseFloat(value).toFixed(2) : null;
            });
            
            const key = id.trim();
            if (!map1.has(key)) {
                map1.set(key, []);
            }
            map1.get(key).push(values);
        });

        const map2 = new Map();
        json2.forEach(item => {
            const id = fields2[idname] !== -1 ? item[`column${fields2[idname] + 1}`] : null;
            if (!id || id.trim() === '') return;
            
            const values = {};
            compareFields.forEach(field => {
                const index = fields2[field];
                // 格式化金额：去除千位分隔符，保留两位小数
                const value = item[`column${index + 1}`]?.replace(/,/g, '');
                values[field] = index !== -1 && !isNaN(parseFloat(value)) ?
                    parseFloat(value).toFixed(2) : null;
            });
            
            const key = id.trim();
            if (!map2.has(key)) {
                map2.set(key, []);
            }
            map2.get(key).push(values);
        });

        // 比较数据，处理重复项
        const differences = [];
        map1.forEach((values1Array, key) => {
            if (map2.has(key)) {
                const values2Array = map2.get(key);
                
                // 对每一个第一组数据中的值
                values1Array.forEach(value1 => {
                    // 对每一个第二组数据中的值
                    values2Array.forEach(value2 => {
                        const diff = {key};
                        let hasDiff = false;
                        
                        compareFields.forEach(field => {
                            if (value1[field] !== value2[field]) {
                                diff[`${field}1`] = value1[field];
                                diff[`${field}2`] = value2[field];
                                hasDiff = true;
                            }
                        });
                        
                        if (hasDiff) {
                            differences.push(diff);
                        }
                    });
                });
            }
        });

        // 生成表格行
        differences.forEach(diff => {
            const tr = document.createElement('tr');
            // 添加查询字段值
            const tdKey = document.createElement('td');
            tdKey.textContent = diff.key;
            tdKey.style.border = '1px solid black';
            tdKey.style.padding = '5px';
            tdKey.style.verticalAlign = 'top';
            tdKey.style.maxHeight = '50px';  // 固定高度
            tdKey.style.overflow = 'hidden'; // 超出部分隐藏
            tdKey.style.whiteSpace = 'nowrap'; // 禁止换行
            tdKey.style.textOverflow = 'ellipsis'; // 超出显示省略号
            tr.appendChild(tdKey);

            // 动态添加比较字段值
            compareFields.forEach(field => {
                const td1 = document.createElement('td');
                td1.textContent = diff[`${field}1`] || '';
                td1.style.border = '1px solid black';
                td1.style.padding = '5px';
                td1.style.verticalAlign = 'top';
                td1.style.maxHeight = '50px';  // 固定高度
                td1.style.maxWidth = '30vw';   // 最大宽度为页面宽度的30%
                td1.style.overflow = 'hidden'; // 超出部分隐藏
                td1.style.whiteSpace = 'nowrap'; // 禁止换行
                td1.style.textOverflow = 'ellipsis'; // 超出显示省略号
                tr.appendChild(td1);

                const td2 = document.createElement('td');
                td2.textContent = diff[`${field}2`] || '';
                td2.style.border = '1px solid black';
                td2.style.padding = '5px';
                td2.style.verticalAlign = 'top';
                td2.style.maxHeight = '50px';  // 固定高度
                td2.style.maxWidth = '30vw';   // 最大宽度为页面宽度的30%
                td2.style.overflow = 'hidden'; // 超出部分隐藏
                td2.style.whiteSpace = 'nowrap'; // 禁止换行
                td2.style.textOverflow = 'ellipsis'; // 超出显示省略号
                tr.appendChild(td2);
            });

            table.appendChild(tr);

            // 获取表头信息
            const table1 = document.querySelector('#table-container table');
            const table2 = document.querySelector('#table-container2 table');
            const json1 = JSON.parse(document.getElementById('json-output').value);
            const json2 = JSON.parse(document.getElementById('json-output2').value);


            // 在两个表格中标记有差异的行
            highlightDiffRow(table1, diff.key);
            highlightDiffRow(table2, diff.key);
        });


        compareContainer.appendChild(table);
    }

    // 新增：高亮显示有差异的行
    function highlightDiffRow(table, settlement) {

        // 获取结算号列索引
        const settlementIndex = getColumnIndex(table, '结算号');
        if (settlementIndex === -1) return;
        const rows = table.querySelectorAll('tr');
        rows.forEach(row => {
            const cells = row.querySelectorAll('td');
            if (cells.length > 0 && cells[settlementIndex].textContent === settlement) {
                row.style.backgroundColor = '#ffcccc'; // 设置红色背景
            }
        });
    }

    // 新增：获取列索引函数
    function getColumnIndex(table, columnName) {
        // 获取第一行数据
        const firstRow = table.querySelector('tr');
        if (!firstRow) return -1;

        // 获取所有单元格
        const cells = firstRow.querySelectorAll('td');
        for (let i = 0; i < cells.length; i++) {
            if (cells[i].textContent.includes(columnName)) {
                return i;
            }
        }
        return -1;
    }

    // 新增：排序功能
    document.querySelector('.sort').addEventListener('click', () => {
        convertTabs('input', 'output', 'json-output', 'table-container');
        convertTabs('input2', 'output2', 'json-output2', 'table-container2')
        const sortFields = document.getElementById('sortFields').value
            .split(/[,，]/)
            .map(f => f.trim())
            .filter(f => f.length > 0);

        // 获取两组数据
        const json1 = JSON.parse(document.getElementById('json-output').value);
        const json2 = JSON.parse(document.getElementById('json-output2').value);

        // 获取表头信息
        const table1 = document.querySelector('#table-container table');
        const table2 = document.querySelector('#table-container2 table');

        // 获取列索引（确保只使用表头行）
        const getFieldIndices = (table) => {
            const indices = {};
            const headerRow = table.rows[0];
            if (headerRow) {
                const cells = headerRow.querySelectorAll('td');
                sortFields.forEach(field => {
                    for (let i = 0; i < cells.length; i++) {
                        if (cells[i].textContent.includes(field)) {
                            indices[field] = i;
                            break;
                        }
                    }
                });
            }
            return indices;
        };

        // 获取字段索引
        const fields1 = getFieldIndices(table1);
        const fields2 = getFieldIndices(table2);

        // 创建第二组数据的映射（从第二行开始）
        const map2 = new Map();
        const rows = table2.querySelectorAll('tr');
        const unmatchedData = [];  // 用于存储未匹配的数据
        const unmatchedDataFromTable1 = [];
        
        // 创建一个映射，用于跟踪相同键的数据
        const keyRowsMap = new Map(); // 键是排序字段的值，值是行索引数组

        for (let i = 1; i < rows.length; i++) {
            const cells = rows[i].querySelectorAll('td');
            const item = {};
            cells.forEach((cell, index) => {
                item[`column${index + 1}`] = normalizeAmount(cell.textContent);
            });
            const key = sortFields.map(field => {
                const index = fields2[field];
                return index !== -1 ? item[`column${index + 1}`] : null;
            }).join('|');
            
            // 将行索引添加到相同键的数组中
            if (!keyRowsMap.has(key)) {
                keyRowsMap.set(key, []);
            }
            keyRowsMap.get(key).push(i);
            
            map2.set(key, item);
            unmatchedData.push({key, item, rowIndex: i});
        }

        // 按第一组顺序创建新数组
        const sortedData = [];
        const matchedKeys = new Set();  // 用于记录已匹配的key
        const usedRows = new Set();    // 用于记录已经使用的行

        for (let i = 1; i < table1.rows.length; i++) {
            const cells = table1.rows[i].querySelectorAll('td');
            const item1 = {};
            cells.forEach((cell, index) => {
                item1[`column${index + 1}`] = normalizeAmount(cell.textContent);
            });
            const key = sortFields.map(field => {
                const index = fields1[field];
                return index !== -1 ? item1[`column${index + 1}`] : null;
            }).join('|');

            // 限制最大查找行数
            let found = false;
            const maxSearchRows = 5000;

            // 从第二组头部开始查找，跳过已经使用的行
            for (let j = 1; j < table2.rows.length && j <= maxSearchRows; j++) {
                if (usedRows.has(j)) continue;  // 跳过已经使用的行

                const cells2 = table2.rows[j].querySelectorAll('td');
                const item2 = {};
                cells2.forEach((cell, index) => {
                    // 仅对排序字段进行金额标准化
                    const isSortField = sortFields.some(field => {
                        const fieldIndex = fields2[field];
                        return fieldIndex !== -1 && index === fieldIndex;
                    });
                    item2[`column${index + 1}`] = isSortField ? normalizeAmount(cell.textContent) : cell.textContent;

                });
                const key2 = sortFields.map(field => {
                    const index = fields2[field];
                    return index !== -1 ? item2[`column${index + 1}`] : null;
                }).join('|');

                if (!map2.has(key) && !unmatchedDataFromTable1.some(item => item.key === key)) {
                    unmatchedDataFromTable1.push({key, item: item1});
                }

                if (!map2.has(key)) {
                    unmatchedDataFromTable1.push({key, item: item1});
                }

                if (key === key2) {
                    sortedData.push(item2);
                    matchedKeys.add(key2);  // 记录已匹配的key
                    usedRows.add(j);       // 标记该行已使用
                    found = true;
                    break;
                }
            }

            if (!found) {
                sortedData.push(createEmptyRow(table2));
            }
        }

        // 添加未匹配的数据
        // 使用keyRowsMap来跟踪相同键的数据，确保所有未使用的行都被添加
        keyRowsMap.forEach((rowIndices, key) => {
            // 过滤出没有被使用的行索引
            const unusedRowIndices = rowIndices.filter(rowIndex => !usedRows.has(rowIndex));
            
            // 如果这个键有未使用的行
            if (unusedRowIndices.length > 0) {
                // 遍历所有未使用的行，将它们添加到结果中
                unusedRowIndices.forEach(rowIndex => {
                    const cells = table2.rows[rowIndex].querySelectorAll('td');
                    const item = {};
                    cells.forEach((cell, index) => {
                        item[`column${index + 1}`] = normalizeAmount(cell.textContent);
                    });
                    
                    // 标记为错误并添加到结果中
                    item['err'] = 1;
                    sortedData.push(item);
                });
            }
        });
        // 更新第一组表格
        updateTable(table1, json1, false);
        // 更新第二组表格（保留表头）
        updateTable(table2, sortedData, true);

        // 修改：在显示未匹配数据之前，过滤掉重复项
        const uniqueUnmatchedData = unmatchedData.filter(({key}) => !matchedKeys.has(key));
        const uniqueUnmatchedDataFromTable1 = unmatchedDataFromTable1.filter(({key}) => !matchedKeys.has(key));

        // 显示未匹配的数据
        showUnmatchedData(uniqueUnmatchedData, uniqueUnmatchedDataFromTable1, matchedKeys);

    });


    // 修改：创建空行，使用全角空格
    function createEmptyRow(table) {
        const rowCount = table.querySelector('tr')?.querySelectorAll('td').length || 0;
        const emptyRow = {};
        for (let i = 1; i <= rowCount; i++) {
            emptyRow[`column${i}`] = '　';  // 使用全角空格
        }
        return emptyRow;
    }

    // 新增：更新表格
    function updateTable(table, data, update) {

        // 保存表头行
        const headerRow = table.rows[0];
        if (update == true) {
            while (table.rows.length > 1) {
                table.deleteRow(1);  // 只删除数据行，保留索引0的表头
            }

            // 添加新数据时仅创建<tr>，没有<th>元素
            data.forEach(rowData => {
                const tr = document.createElement('tr');
                if (rowData.err) {
                    tr.style.backgroundColor = '#ffcccc'; // 设置红色背景
                    delete rowData.err;
                }
                Object.values(rowData).forEach(cell => {
                    const td = document.createElement('td');
                    td.textContent = cell;
                    td.style.border = '1px solid black';
                    td.style.padding = '5px';
                    td.style.verticalAlign = 'top';
                    td.style.maxHeight = '50px';
                    td.style.maxWidth = '30vw';
                    td.style.overflow = 'hidden';
                    td.style.whiteSpace = 'nowrap';
                    td.style.textOverflow = 'ellipsis';
                    tr.appendChild(td);
                });
                // 检查是否整行都为空
                const isEmptyRow = Object.values(rowData).every(cell => cell.trim() === '' || cell === '　');
                if (isEmptyRow) {
                    tr.style.backgroundColor = '#ffcccc'; // 设置红色背景
                }
                table.appendChild(tr);
            });
        }


        // 添加合计行
        const totalRow = document.createElement('tr');
        const totalCell = document.createElement('td');
        totalCell.textContent = '合计';
        totalCell.colSpan = 1; // 第一列只显示"合计"
        totalCell.style.textAlign = 'center';
        totalCell.style.fontWeight = 'bold';
        totalCell.style.backgroundColor = '#f0f0f0';
        totalRow.appendChild(totalCell);

        // 获取比较字段和排序字段
        const compareFields = document.getElementById('compareFields').value
            .split(/[,，或 　]/)
            .map(f => f.trim())
            .filter(f => f.length > 0);
        const sortFields = document.getElementById('sortFields').value
            .split(/[,，]/)
            .map(f => f.trim())
            .filter(f => f.length > 0);

        // 获取列索引
        const fields = [...new Set([...compareFields, ...sortFields])];
        const indices = {};
        // 使用保存的表头行获取列索引，而不是当前可能已经变化的表头
        headerRow.querySelectorAll('td').forEach((td, index) => {
            fields.forEach(field => {
                if (td.textContent.includes(field)) {
                    indices[field] = index;
                }
            });
        });
        // 计算合计值
        const totals = {};
        fields.forEach(field => {
            totals[field] = 0;
        });

        data.forEach(rowData => {
            fields.forEach(field => {
                const index = indices[field];
                if (index !== undefined) {
                    const value = parseFloat(rowData[`column${index + 1}`]?.replace(/,/g, '') || 0);
                    if (!isNaN(value)) {
                        totals[field] += value;
                    }
                }
            });
        });

        // 添加合计值
        fields.forEach(field => {
            const index = indices[field];
            if (index !== undefined) {
                // 添加空单元格直到到达合计列
                while (totalRow.cells.length < index) {
                    const emptyCell = document.createElement('td');
                    emptyCell.textContent = '';
                    totalRow.appendChild(emptyCell);
                }
                const td = document.createElement('td');
                td.textContent = totals[field].toFixed(2);
                td.style.border = '1px solid black';
                td.style.padding = '5px';
                td.style.textAlign = 'right';
                td.style.fontWeight = 'bold';
                td.style.backgroundColor = '#f0f0f0';
                totalRow.appendChild(td);
            }
        });

        table.appendChild(totalRow);


    }

    function addTotalRow(table) {
        // 检查是否已经存在合计行
        const hasTotalRow = Array.from(table.rows).some(row =>
            row.cells[0] && row.cells[0].textContent.includes('合计')
        );
        if (hasTotalRow) return;

        // 创建合计行
        const totalRow = document.createElement('tr');
        const totalCell = document.createElement('td');
        totalCell.textContent = '合计';
        totalCell.colSpan = table.rows[0].cells.length;
        totalCell.style.textAlign = 'center';
        totalCell.style.fontWeight = 'bold';
        totalCell.style.backgroundColor = '#f0f0f0';
        totalRow.appendChild(totalCell);
        table.appendChild(totalRow);
    }

    // 新增：金额标准化函数
    function normalizeAmount(value) {
        // 去除千位分隔符
        const numStr = value.replace(/,/g, '');

        // 判断是否为有效数字
        if (/^-?\d+(\.\d+)?$/.test(numStr)) {
            const num = Number(numStr);
            // 如果是整数，添加.00
            if (numStr.indexOf('.') === -1) {
                return num.toFixed(2);
            }
            // 如果是浮点数，保留两位小数
            return num.toFixed(2);
        }
        // 非数字保持原样
        return value;
    }

    // 新增：高亮显示未匹配的行
    function highlightUnmatchedRow(table, key) {
        const rows = table.querySelectorAll('tr');
        rows.forEach(row => {
            const cells = row.querySelectorAll('td');
            // 检查第一列是否匹配key
            if (cells.length > 0 && cells[0].textContent === key) {
                row.style.backgroundColor = '#ffcccc'; // 设置红色背景
            }
        });
    }

    // 新增：显示未匹配数据的函数
    function showUnmatchedData(unmatchedData, unmatchedDataFromTable1, matchedKeys) {
        const compareContainer = document.getElementById('compare-container');
        compareContainer.innerHTML = '';

        // 获取两个表格
        const table1 = document.querySelector('#table-container table');
        const table2 = document.querySelector('#table-container2 table');


        // 创建表格
        const table = document.createElement('table');
        table.style.border = '1px solid black';
        table.style.borderCollapse = 'collapse';

        // 创建表头
        const headerRow = document.createElement('tr');
        ['Source', 'Key', 'Data'].forEach(text => {
            const th = document.createElement('th');
            th.textContent = text;
            th.style.border = '1px solid black';
            th.style.padding = '5px';
            headerRow.appendChild(th);
        });
        table.appendChild(headerRow);

        // 添加未匹配的数据
        unmatchedData.forEach(({key, item}) => {
            if (!matchedKeys.has(key)) {
                // 高亮table2中未匹配的行
                highlightUnmatchedRow(table2, key);

                const tr = document.createElement('tr');
                tr.style.backgroundColor = '#ffcccc';  // 添加红色背景
                // 添加Source列
                const tdSource = document.createElement('td');
                tdSource.textContent = 'Table2';
                tdSource.style.border = '1px solid black';
                tdSource.style.padding = '5px';
                tr.appendChild(tdSource);

                // 添加Key列
                const tdKey = document.createElement('td');
                tdKey.textContent = key;
                tdKey.style.border = '1px solid black';
                tdKey.style.padding = '5px';
                tr.appendChild(tdKey);

                // 添加Data列
                const tdData = document.createElement('td');
                tdData.textContent = JSON.stringify(item);
                tdData.style.border = '1px solid black';
                tdData.style.padding = '5px';
                tr.appendChild(tdData);

                table.appendChild(tr);
            }
        });

        // 添加table1中未匹配的数据
        const uniqueKeys = new Set();
        unmatchedDataFromTable1.forEach(({key, item}) => {
            // 如果key已经处理过则跳过
            if (uniqueKeys.has(key)) return;
            uniqueKeys.add(key);

            // 高亮table1中未匹配的行
            highlightUnmatchedRow(table1, key);

            const tr = document.createElement('tr');
            tr.style.backgroundColor = '#ffcccc';  // 添加红色背景
            // 添加Source列
            const tdSource = document.createElement('td');
            tdSource.textContent = 'Table1';
            tdSource.style.border = '1px solid black';
            tdSource.style.padding = '5px';
            tr.appendChild(tdSource);

            // 添加Key列
            const tdKey = document.createElement('td');
            tdKey.textContent = key;
            tdKey.style.border = '1px solid black';
            tdKey.style.padding = '5px';
            tr.appendChild(tdKey);

            // 添加Data列
            // 将 item 转换为表格字符串
            const itemTable = createTableFromItem(item);
            tdData.innerHTML = itemTable;
            tdData.style.border = '1px solid black';
            tdData.style.padding = '5px';
            tr.appendChild(tdData);

            table.appendChild(tr);
        });

        compareContainer.appendChild(table);
        //document.getElementById('compareJsonData').style.display = 'none';
    }


</script>
</body>
</html>